package net.sharpf2.api.world;

import java.awt.Point;
import net.sharpf2.algorithm.astar.PathFinder;
import net.sharpf2.api.Globals;
import net.sharpf2.api.Methods;
import net.sharpf2.api.info.Run;
import net.sharpf2.api.interfaces.Logout;
import net.sharpf2.api.interfaces.Minimap;
import net.sharpf2.api.util.Mathematics;

/**
 *
 * @author Rick van Biljouw, Sam Smekens
 */
public class Navigation {

    /**
     * Walks to a specified tile. Logouts if failed.
     * @param   x Tile.
     * @param   y Tile.
     */
    public static void walkTo(int x, int y) {
        navigate(x, y, true);
    }

    /**
     * Walks the specified path.
     * @param path          The path that should be walked
     * @param reverse       Reverse the path? (walking goes from the end of the path, to the beginning of the path)
     * @param run           Use run when energy is >=40
     */
    public static void walkPath(Point[] path, boolean reverse, boolean run){
        if(reverse) path = Mathematics.reverse(path);
        int tries = 0;
        while (Methods.getMyPlayer().getContent().getWorldPosition().distance(path[path.length-1].x, path[path.length-1].y) > 10 && tries < 10 && !Thread.currentThread().isInterrupted()) {
            if(Run.getEnergy() >= 40 && !Run.isRunning()){
                Run.turnRun(true);
            }
            Minimap.walkPath(path);
            tries++;
        }

        if (tries >= 10) {
            Logout.exitToLogin();
        }
    }
    
    /**
     * Walks the specified path.
     * @param path          The path that should be walked
     * @param reverse       Reverse the path-array or not
     */
    public static void walkPath(Point[] path, boolean reverse){
        walkPath(path, reverse, false);
    }
    
    /**
     * Walks the specified path.
     * @param path          The path that should be walked
     */
    public static void walkPath(Point[] p){
        walkPath(p, false, false);
    }
    
    /**
     * Randomizes a specified location.
     * @param   x   Tile.
     * @param   y   Tile.
     * @param   rx  Randomization X.
     * @param   ry  Randomization Y.
     * @return  Returns a randomized point.
     */
    public static Point randomize(int x, int y, int rx, int ry) {
        if ((x > 0 && y > 0) && (rx > 0 && ry > 0)) {
            return new Point(Mathematics.random(x - rx, x + rx), Mathematics.random(y - ry, y + ry));
        }
        return null;
    }

    /**
     * Walks to a specified tile.
     * @param point Tile.
     */
    public static void walkTo(Point point) {
        walkTo(point.x, point.y);
    }

    /**
     * Use pathfinding to navigate to specific tile
     * @param x             Tile.
     * @param y             Tile
     * @param logoutOnFail  True to logout if navigation fails, otherwise false.
     */
    private static void navigate(int x, int y, boolean logoutOnFail) {
        int tries = 0;
        while (Methods.getMyPlayer().getContent().getWorldPosition().distance(x, y) > 10 && tries < 10 && !Thread.currentThread().isInterrupted()) {
            PathFinder pathFinder = new PathFinder(Globals.METHODS);
            Point[] path = pathFinder.getPath(new Point(x, y));
            Minimap.walkPath(path);
            tries++;
        }

        if (tries >= 10 && logoutOnFail) {
            Logout.exitToLogin();
        }
    }
}
